package genetica.algoritmoSeleccion;

import genetica.cromosomas.Cromosoma;
import genetica.cromosomas.factorias.FactoriaCromosomas;

import java.util.ArrayList;
import java.util.Random;

public class ASTorneo extends AlgoritmoSeleccion {
	private Boolean probabilista;
	public Boolean getProbabilista() {
		return probabilista;
	}

	public void setProbabilista(Boolean probabilista) {
		this.probabilista = probabilista;
	}

	public Integer getP() {
		return p;
	}

	public void setP(Integer p) {
		this.p = p;
	}

	private Integer p;

	/**
	 * 
	 * @param probabilista
	 *            Indica si el algoritmo se ejecturada de forma probabilista o
	 *            Determinista
	 * @param p
	 *            número de cromosomas que partician en el torneo
	 */
	public ASTorneo(Boolean probabilista, int p) {
		super();
		this.probabilista = probabilista;
		this.p = p;
	}

	@Override
	public ArrayList<Cromosoma> seleccion(ArrayList<Cromosoma> pob,
			FactoriaCromosomas<Cromosoma> fc) {
		if (this.p > pob.size())
			throw new Error(
					"P no puede ser mayor que el tamaño de la población");
		ArrayList<Cromosoma> nuevaPob = new ArrayList<Cromosoma>(pob.size());
		Random r = new Random();
		// Un for para crear el mismo número
		for (int j = 0; j < pob.size(); j++) {
			// lo copio en un temporal donde ire eliminando los que haya selecionado
			ArrayList<Cromosoma> temp = (ArrayList<Cromosoma>) pob.clone();
			Double aptitudMejor = null;
			Cromosoma cMejor = null;
			Double aptitudPeor = null;
			Cromosoma cPeor = null;
			// P veces
			for (int i = 0; i < p; i++) {
				// posicion escogida 
				int pos = r.nextInt(pob.size());
				// eliminamos el selecionado
				Cromosoma c = temp.get(pos);
				// guardamos el mejor
				if (aptitudMejor == null) {
					cMejor = c;
					aptitudMejor = c.getAptitudNormalizada();
				} else if (c.getAptitudNormalizada() > aptitudMejor) {
//				} else if (c.compareTo(cMejor) > 0){
					cMejor = c;
					aptitudMejor = c.getAptitudNormalizada();
				}
				// si es probabilista guardamos tambien el menor
				if (probabilista) {
					if (aptitudPeor == null) {
						cPeor = c;
						aptitudPeor = c.getAptitudNormalizada();
					} else if (c.getAptitudNormalizada() < aptitudPeor) {
//					} else if (c.compareTo(cPeor) < 0) {
						cPeor = c;
						aptitudPeor = c.getAptitudNormalizada();
					}
				}
				// Boolean al 50% true el peor
				
			}
			if (probabilista && r.nextBoolean()){
				nuevaPob.add(fc.copia(cPeor));
			}else{
				nuevaPob.add(fc.copia(cMejor));
			}
		}
		return nuevaPob; 

	}
	
	@Override
	public String toString(){
		return "Algoritmo de seleccion por Torneo";
	}

}
